`timescale 1ns/100ps

`include "sim_glb.sv"
`include "cpu_rw_axi.sv"

module tc;

localparam          U_DLY                   = 0;
localparam          CLK_PRD                 = 5;
localparam          CPU_AW                 = 16;
localparam          CPU_DW                 = 32;

localparam          ADDR_BW                 = CPU_AW-4;
localparam          DATA_BW                 = CPU_DW;
localparam          MST_NUM                 = 2;

reg                                         rst_n;
reg                                         clk;

reg                 [CPU_DW-1:0]            rdata;

wire                [MST_NUM-1:0]           slv_awhit;     // one-hot combinational logic of slv_awaddr
wire                [MST_NUM-1:0]           slv_arhit;     // one-hot combinational logic of slv_araddr

// several AXI-lite masters(to destination slaves)
wire                [MST_NUM*ADDR_BW-1:0]   mst_awaddr;
wire                [MST_NUM-1:0]           mst_awvalid;
wire                [MST_NUM-1:0]           mst_awready;

wire                [MST_NUM*DATA_BW-1:0]   mst_wdata;
wire                [MST_NUM-1:0]           mst_wvalid;
wire                [MST_NUM-1:0]           mst_wready;

wire                [MST_NUM*2-1:0]         mst_bresp;
reg                 [MST_NUM-1:0]           mst_bvalid;
wire                [MST_NUM-1:0]           mst_bready;

wire                [MST_NUM*ADDR_BW-1:0]   mst_araddr;
wire                [MST_NUM-1:0]           mst_arvalid;
wire                [MST_NUM-1:0]           mst_arready;

reg                 [MST_NUM*DATA_BW-1:0]   mst_rdata;
wire                [MST_NUM*2-1:0]         mst_rresp;
reg                 [MST_NUM-1:0]           mst_rvalid;
wire                [MST_NUM-1:0]           mst_rready;

initial begin:CRG
    rst_n=1'b0;
    clk=1'b0;

    rst_n=#100.5 1'b1;
    forever clk=#CLK_PRD ~clk;
end

RGRS_MNG    rgrs;
initial begin:REGRESS
    rgrs = new("tc_amba", 1);

    rgrs.wait_chks_done(100_000_000);
end

cpu_rw_axi_itf #(CPU_AW, CPU_DW) cpu_rw_axi(clk);

initial begin:AXI_RW
    rdata = 0;

    @(posedge rst_n);

    cpu_rw_axi.cpu_wr_t(5, 16'h0100, 32'h1234_5678);
    cpu_rw_axi.cpu_wr_t(5, 16'h1100, 32'habcd_ef9a);

    cpu_rw_axi.cpu_rd_t(5, 16'h0200, rdata);
    cpu_rw_axi.cpu_rd_t(5, 16'h1300, rdata);

    cpu_rw_axi.cpu_rd_t(5, 16'h2300, rdata);

    #1_000;
    rgrs.one_chk_done("AXI RW is done.");
end

assign slv_awhit[0] = (cpu_rw_axi.awaddr[ADDR_BW+:4]==4'h0) ? 1'b1 : 1'b0;
assign slv_awhit[1] = (cpu_rw_axi.awaddr[ADDR_BW+:4]==4'h1) ? 1'b1 : 1'b0;

assign slv_arhit[0] = (cpu_rw_axi.araddr[ADDR_BW+:4]==4'h0) ? 1'b1 : 1'b0;
assign slv_arhit[1] = (cpu_rw_axi.araddr[ADDR_BW+:4]==4'h1) ? 1'b1 : 1'b0;

axi_lite_split #(
        .ADDR_BW                        (ADDR_BW                        ),
        .DATA_BW                        (DATA_BW                        ),
        .SLV_REG                        (1'b0                           ),	// source reg slicer
        .MST_NUM                        (2                              ),
        .MST_REG                        ({MST_NUM{1'b1}}                )	// each bit for a destination reg slicer, 1'b1:add slice reg; 1'b0:no slice reg
) u_axi_lite_split ( 
        .rst_n                          (rst_n                          ),
        .clk                            (clk                            ),

// address decoder
        .slv_awhit                      (slv_awhit                      ),	// one-hot combinational logic of slv_awaddr
        .slv_arhit                      (slv_arhit                      ),	// one-hot combinational logic of slv_araddr

// one AXI-lite slave(from source master)
        .slv_awaddr                     (cpu_rw_axi.awaddr[0+:ADDR_BW]  ),
        .slv_awvalid                    (cpu_rw_axi.awvalid             ),
        .slv_awready                    (cpu_rw_axi.awready             ),

        .slv_wdata                      (cpu_rw_axi.wdata               ),
        .slv_wvalid                     (cpu_rw_axi.wvalid              ),
        .slv_wready                     (cpu_rw_axi.wready              ),

        .slv_bresp                      (cpu_rw_axi.bresp               ),
        .slv_bvalid                     (cpu_rw_axi.bvalid              ),
        .slv_bready                     (cpu_rw_axi.bready              ),

        .slv_araddr                     (cpu_rw_axi.araddr[0+:ADDR_BW]  ),
        .slv_arvalid                    (cpu_rw_axi.arvalid             ),
        .slv_arready                    (cpu_rw_axi.arready             ),

        .slv_rdata                      (cpu_rw_axi.rdata               ),
        .slv_rresp                      (cpu_rw_axi.rresp               ),
        .slv_rvalid                     (cpu_rw_axi.rvalid              ),
        .slv_rready                     (cpu_rw_axi.rready              ),

// several AXI-lite masters(to destination slaves)
        .mst_awaddr                     (mst_awaddr                     ),
        .mst_awvalid                    (mst_awvalid                    ),
        .mst_awready                    (mst_awready                    ),

        .mst_wdata                      (mst_wdata                      ),
        .mst_wvalid                     (mst_wvalid                     ),
        .mst_wready                     (mst_wready                     ),

        .mst_bresp                      (mst_bresp                      ),
        .mst_bvalid                     (mst_bvalid                     ),
        .mst_bready                     (mst_bready                     ),

        .mst_araddr                     (mst_araddr                     ),
        .mst_arvalid                    (mst_arvalid                    ),
        .mst_arready                    (mst_arready                    ),

        .mst_rdata                      (mst_rdata                      ),
        .mst_rresp                      (mst_rresp                      ),
        .mst_rvalid                     (mst_rvalid                     ),
        .mst_rready                     (mst_rready                     )
);


genvar g0;
generate for (g0=0; g0<MST_NUM; g0=g0+1) begin:G_SIM_SLV
    assign mst_awready[g0] = mst_awvalid[g0];
    assign mst_wready[g0]  = mst_wvalid[g0];
    assign mst_arready[g0] = mst_arvalid[g0];
    
    always@(posedge clk or negedge rst_n) begin
        if (rst_n==1'b0) begin
            mst_bvalid[g0] <=`U_DLY 1'b0;
            mst_rvalid[g0] <=`U_DLY 1'b0;
            mst_rdata[g0*DATA_BW+:DATA_BW] <=`U_DLY {DATA_BW{1'b0}};
        end else begin
            if (mst_wvalid[g0]==1'b1 && mst_wready[g0]==1'b1)
                mst_bvalid[g0] <=`U_DLY 1'b1;
            else if (mst_bready[g0]==1'b1)
                mst_bvalid[g0] <=`U_DLY 1'b0;
            else
                ;

            if (mst_arvalid[g0]==1'b1 && mst_arready[g0]==1'b1)
                mst_rvalid[g0] <=`U_DLY 1'b1;
            else if (mst_rready[g0]==1'b1)
                mst_rvalid[g0] <=`U_DLY 1'b0;
            else
                ;

            if (mst_wvalid[g0]==1'b1 && mst_wready[g0]==1'b1)
                mst_rdata[g0*DATA_BW+:DATA_BW] <=`U_DLY mst_wdata[g0*DATA_BW+:DATA_BW];
            else
                ;
        end
    end

    assign mst_bresp[g0*2+:2] = g0;
    assign mst_rresp[g0*2+:2] = g0;
end endgenerate

endmodule
